#include "lvgl/lvgl.h"
#include <SDL2/SDL.h>
#include "slider_component.h"
// ✅lv_event_code_t filter 事件类型：
// 事件	                    说明
// LV_EVENT_PRESSED	        用户刚按下滑块时触发回调函数（开始拖动）
// LV_EVENT_PRESSING	    只要用户按着坏块即使值没变化也会持续触发回调函数
// LV_EVENT_RELEASED	    用户刚松开滑块时触发回调函数（拖动结束）
// LV_EVENT_VALUE_CHANGED	只有slider的值发生变化时才会触发回调函数，一般拖动过程值都会发生变化都会触发，按着不拖动情况值没变化不会触发

/**
 * 设置slider是否可用
 *
 * @param slider 进度条
 * @param enable slider是否可用，false：滑块会变灰，无法响应用户事件（拖动、点击等），程序仍可通过 lv_slider_set_value() 修改其值。
 * @return
 */
void config_enable_slider(lv_obj_t *slider, _Bool enable) {
    if (enable)
    {
        //取消禁用slider
        lv_obj_clear_state(slider, LV_STATE_DISABLED);
        return;
    }
    //禁用slider
    lv_obj_add_state(slider, LV_STATE_DISABLED);
}
/**
 * 给slider添加事件监听回调方法
 * @param slider 进度条
 * @param event_cb 回调方法
 * @param filter 监听事件类型
 * @param user_data 自定义回调方法数据
 * @return
 */
void add_slider_event_observer(lv_obj_t *slider,
                              lv_event_cb_t event_cb,
                              enum slider_event_observer_type event_observer_type,
                              void *user_data) {
    lv_event_code_t filter;
    switch (event_observer_type)
    {
    case touch_down_pressed:{
        filter = LV_EVENT_PRESSED;
        break;
    }
    case pressing:{
        filter = LV_EVENT_PRESSING;
        break;
    }
    case touchup_released:{
        filter = LV_EVENT_RELEASED;
        break;
    }
    case value_changed:{
        filter = LV_EVENT_VALUE_CHANGED;
        break;
    }
    default:
        break;
    }
    lv_obj_add_event_cb(slider, event_cb, filter, user_data);
}

/**
 * 给slider添加拖拽过程回调方法，拖动过程中不断触发
 * @param slider 进度条
 * @param event_cb 回调方法
 * @param filter 事件类型
 * @param user_data 自定义回调方法数据
 * @return
 */
void draging_observer(lv_obj_t *slider,
                    lv_event_cb_t event_cb,
                    lv_event_code_t filter,
                    void *user_data) {
    lv_obj_add_event_cb(slider, event_cb, filter, user_data);
}

/**
 * 是否正在拖拽slider滑块
 * @param slider 进度条
 * @return _Bool 是否正在拖拽slider滑块
 */
_Bool is_draging(lv_obj_t *slider) {
    return lv_slider_is_dragged(slider);
}

/**
 * 给slider和label设置进度
 * @param slider 进度条
 * @param label 进度标签
 * @param gone_count 已完成数量
 * @param total_count 总数量
 * @return _Bool 是否正在拖拽slider滑块
 */
void config_slider_progress(lv_obj_t *slider,
                          lv_obj_t *label,
                          Uint32 gone_count,
                          Uint32 total_count) {
    // 已完成数量gone_count除以总数量total_count得到已完成百分比
    // ✅除法的除数和被除数都是Uint32等整型数据时得到的也是取整数据，相当于多少倍的意思，取整后得到的进度一直是0
    // 因此此处除数和被除数至少一个需转为double才能得到0.xxx
    double progress = ((double)gone_count / (double)total_count) * 100.0;
    // printf("config_slider_progress gone_count:%u,total_count:%u, progress:%f\n", gone_count, total_count, progress);

    if (progress > 100.0) progress = 100.0;
    if (slider != NULL)
    {
        // 报错❌：[Error] (10.542, +10542) lv_bar_set_value: Asserted at expression: obj != NULL (The object is NULL) lv_bar.c:97
        // 原因分析✅：lv_bar_set_value第一个参数music_slider为NULL
        // 解决办法✅：调用前判断是否为NULL避免程序崩溃，然后确保music_slider对象有初始化创建成功即不为NULL
        lv_slider_set_value(slider, progress, LV_ANIM_OFF);

        char buf[5];//缓冲区，最长情况为100%四个字符再加上结束符\0共5个字符即最长5个字符，此处缓冲区设置5个字符就够用了
        /*把获取的滑块值写入buf中*/
        int slider_value = (int)progress;
        lv_snprintf(buf, sizeof(buf), "%d%%", slider_value);
        /*把buf中的内容显示在label上*/
        lv_label_set_text(label, buf);
    }
}
